/*
 * ledmatrix.c
 *
 *  Created on: Mar 09, 2010
 *      Author: Orlando Arias
 *	   License: GPLv3
 *
 *   libLEDMatrix for Arduino Systems
 *   Copyright (C) 2010  Orlando Arias
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <WProgram.h>
#include "ledmatrix.h"

inline void lmx_strobe(uint8_t s);

void lmx_init(ledmatrix *l){
	// initialize MCU pinout
	pinMode(l->data_in, OUTPUT);
	pinMode(l->clk, OUTPUT);
}

void lmx_sendData(ledmatrix *l, uint8_t data){
	// clock data into shift register
	for (uint8_t i = 0; i<7; i++){
		digitalWrite(l->data_in, data & (uint8_t) 0x01);	// send LSB
		delayMicroseconds(LMX_SREG_PROP_DELAY); // wait propagation time
		lmx_strobe(l->clk);						// clock
		data >>= (uint8_t) 1;					// shift data
	}
}

inline void lmx_clearSreg(ledmatrix *l){
	/*
	 *  The precompiler inserts code from inline function
	 *  wherever this one is called, thereby reducing final
	 *  code generation from
	 *  0e 94 00 00		call 	adr1 	; 0xadr1 <lmx_sendData>
	 *  ...
	 *  ;; start of lmx_clearSreg
	 *  60 e0           ldi     r22, 0x00       ; 0
	 *  0e 94 00 00     call    adr2    ; 0xadr2 <lmx_sendData>
	 *  08 95           ret
	 *
	 *  to
	 *  0e 94 00 00		call 	adr2	; 0xadr2 <lmx_sendData>
	 *  saving 8 bytes of program ram every time the function is called
	 */
	lmx_sendData(l, 0);
}

inline void lmx_strobe(uint8_t s){
	/*
	 *  generate a clock pulse
	 *  separated as inline function for code sanity
	 */
	digitalWrite(s, HIGH);
	delayMicroseconds(LMX_SREG_CLK_DELAY);
	digitalWrite(s, LOW);
}
